package com.qingcloud.adminbackend.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qingcloud.adminbackend.constant.WamingConstant;
import com.qingcloud.adminbackend.base.AjaxResult;
import com.qingcloud.adminbackend.entity.role.RolePageRequest;
import com.qingcloud.adminbackend.entity.role.SysRole;
import com.qingcloud.adminbackend.entity.role.SysRoleDto;
import com.qingcloud.adminbackend.entity.role.SysRoleTableDTO;
import com.qingcloud.adminbackend.entity.sysfunction.SysFunction;
import com.qingcloud.adminbackend.entity.sysfunction.SysRoleFunction;
import com.qingcloud.adminbackend.entity.sysorg.SysBusinessTypeDTO;
import com.qingcloud.adminbackend.entity.user.SysUser;
import com.qingcloud.adminbackend.enums.DataFunctionEnum;
import com.qingcloud.adminbackend.mapper.SysFunctionMapper;
import com.qingcloud.adminbackend.mapper.SysOrderMapper;
import com.qingcloud.adminbackend.mapper.SysRoleFunctionMapper;
import com.qingcloud.adminbackend.mapper.SysRoleMapper;
import com.qingcloud.adminbackend.service.ISysRoleService;
import com.qingcloud.adminbackend.service.ISysUserService;
import com.qingcloud.adminbackend.utils.CommonUtil;
import com.qingcloud.adminbackend.utils.DateUtil;
import com.qingcloud.base.constant.SecurityConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author wangjinnan
 * @since 2018-12-19
 */
@Service
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRole> implements ISysRoleService {

    private static final Logger logger = LoggerFactory.getLogger(SysRoleServiceImpl.class);

    @Resource
    private SysFunctionMapper sysFunctionMapper;

    @Resource
    private SysRoleMapper sysRoleMapper;

    @Resource
    private SysRoleFunctionMapper sysRoleFunMapper;
    @Resource
    private ISysUserService sysUserService;

    @Resource
    private SysOrderMapper sysOrderMapper;

    /**
     * 用户Type查询用户身份
     *
     * @param roleType
     * @return
     */
    @Override
    public List<SysRole> getRoleIdentity(String roleType, String userId) {
        // admin查询所有身份
        return sysRoleMapper.getRoleWithRoleType(roleType);
    }

    @Override
    @Transactional
    public AjaxResult<String> addSysRole(SysRoleDto role, String loginUserId) {
        AjaxResult<String> result = checkRoleValidation(role, true);
        if (result != null && result.getErroCode() != WamingConstant.SUCCESS)
            return result;
        role.setDeleteFlag(WamingConstant.DELETE_FLAG_NORMAL);
        role.setCreateBy(loginUserId);
        role.setModifyBy(loginUserId);
        role.setCreateDt(DateUtil.strDateFormat(new Date()));
        role.setModifyDt(DateUtil.strDateFormat(new Date()));
        int insert1 = sysRoleMapper.addSysRole(role);
        String funId = role.getFunIds();
        if (insert1 <= 0) return new AjaxResult<>(WamingConstant.FAILURE, "添加角色失败", "");
        if (funId != null) {
            String[] funIds = funId.split(",");
            List<SysRoleFunction> roleFunctionList = new ArrayList<>();
            Arrays.asList(funIds).forEach(it -> {
                SysRoleFunction roleFunction = new SysRoleFunction();
                roleFunction.setRoleId(String.valueOf(role.getId()));
                roleFunction.setFunctionId(it);
                roleFunction.setCreateBy(loginUserId);
                roleFunction.setModifyBy(loginUserId);
                roleFunction.setCreateDt(DateUtil.strDateFormat(new Date()));
                roleFunction.setModifyDt(DateUtil.strDateFormat(new Date()));
                roleFunctionList.add(roleFunction);
            });
            if (roleFunctionList.size() > 0) {
                int insert = sysRoleFunMapper.insert0(roleFunctionList);
                if (insert > 0) return new AjaxResult<>(WamingConstant.SUCCESS, "", "");
                else return new AjaxResult<>(WamingConstant.FAILURE, "添加角色功能失败", "");

            }
            return new AjaxResult<>(WamingConstant.SUCCESS, "", "");
        }
        return new AjaxResult<>(WamingConstant.FAILURE, "添加角色失败", "");
    }

    @Override
    public AjaxResult<String> updateSysRole(SysRoleDto role) {
        int insertFlag = sysRoleMapper.updateSysRole(role);
        sysRoleFunMapper.deleteByRoleIds(new String[]{role.getId() + ""});
        if (role.getFunIds() != null && !role.getFunIds().equals("")) {
            List<SysRoleFunction> roleFunctionList = new ArrayList<>();
            String[] split = role.getFunIds().split(",");
            for (String s : split) {
                SysRoleFunction roleFunction = new SysRoleFunction();
                roleFunction.setRoleId(role.getId() + "");
                roleFunction.setFunctionId(s);
                roleFunction.setModifyBy(role.getModifyBy());
                roleFunction.setModifyDt(DateUtil.getCurrentDate());
                roleFunctionList.add(roleFunction);
            }
            sysRoleFunMapper.insert0(roleFunctionList);
        }

        if (insertFlag > 0) return new AjaxResult<>(WamingConstant.SUCCESS, "修改成功", "");
        else return new AjaxResult<>(WamingConstant.FAILURE, "修改失败", "");
    }

    @Override
    public AjaxResult<String> deleteRoles(Integer[] roleIds, String loginUserId) {
        int insertFlag = sysRoleMapper.deleteByRoleIds(Arrays.asList(roleIds), loginUserId, new Date());
        if (insertFlag > 0) return new AjaxResult<>(WamingConstant.SUCCESS, "删除成功", "");
        else return new AjaxResult<>(WamingConstant.FAILURE, "删除失败", "");
    }

    @Override
    public AjaxResult<List<SysRole>> findRolesByIds(Integer[] roleIds) {
        List<SysRole> roleList = sysRoleMapper.findRolesByIds(Arrays.asList(roleIds));
        for (SysRole sysRole : roleList) {
            List<String> fidList = sysRoleMapper.findFunctionIdByRoleId(sysRole.getId());
            sysRole.setFunIds(CollUtil.join(fidList, ","));
        }
        return new AjaxResult<>(WamingConstant.SUCCESS, "", roleList);
    }

    @Override
    public IPage<SysRoleTableDTO> page(RolePageRequest rolePageRequest) {
        //框架分页参数对象
        Page<SysRole> page = new Page<>(rolePageRequest.getCurrentPage(), rolePageRequest.getPerPage());
        if (StrUtil.isNotBlank(rolePageRequest.getName())) {
            //名称加上sql模糊
            rolePageRequest.setName("%" + rolePageRequest.getName() + "%");
        }

        SysUser sysUser = sysUserService.getById(rolePageRequest.getUserId());
        if ((sysUser.getAdminFlag() != null && sysUser.getAdminFlag() == 1)
                || sysUser.getUserName().equals(SecurityConstants.ADMIN_USER_NAME)) {
            rolePageRequest.setAdmin(true);
        }
        if ((sysUser.getAdminFlag() != null && sysUser.getAdminFlag() != 1)
                && !sysUser.getUserName().equals(SecurityConstants.ADMIN_USER_NAME)
                && (sysUser.getOrgAdmin() != null && sysUser.getOrgAdmin() == 1)) {//组织管理员
            rolePageRequest.setOrgAdmin(true);
        }
        //有权限的应用ID
        Set<Integer> businessSet = sysOrderMapper.getBusinessTypeByUserId(sysUser.getId(), rolePageRequest.isAdmin(), rolePageRequest.isOrgAdmin())
                .stream().map(it -> Integer.parseInt(it.getValue())).collect(Collectors.toSet());
        if (CollUtil.isEmpty(businessSet)) {
            return new Page<>();
        }
        IPage<SysRoleTableDTO> rolePage = sysRoleMapper.searchPage(page, rolePageRequest, businessSet);
        if (CollUtil.isNotEmpty(rolePage.getRecords())) {
            //设置数据权限
            for (SysRoleTableDTO record : rolePage.getRecords()) {
                final String dataFunction = record.getDataFunction();
                if (StrUtil.isNotBlank(dataFunction)) {
                    final StringJoiner stringJoiner = new StringJoiner(",");
                    final String[] split = dataFunction.split(",");
                    for (String code : split) {
                        stringJoiner.add(DataFunctionEnum.getNameByCode(Integer.valueOf(code)));
                    }
                    record.setDataFunction(stringJoiner.toString());
                }
            }
        }
        return rolePage;
    }

    @Override
    public AjaxResult<List<SysRole>> findRoles() {
        return new AjaxResult<>(WamingConstant.SUCCESS, "", sysRoleMapper.findRoles());
    }

    private AjaxResult<String> checkRoleValidation(SysRoleDto role, boolean isNew) {
        //修改角色不需要判断有效性
        if (!isNew) {
            return null;
        }
        if (CommonUtil.isEmpty(role.getName()))
            return new AjaxResult<>(3000, "角色名称不能为空", null);
        Integer countForName = sysRoleMapper.countRoleForValidName(role.getName(), isNew ? null : role.getId());
        if (countForName != null && countForName > 0) {
            return new AjaxResult<>(3000, "输入的角色名称已经存在", null);
        }

        //校验传入的funIds是否都是有效的id
        String[] funIds = role.getFunIds() == null ? new String[0] : role.getFunIds().split(",");
        if (funIds.length > 0) {
            List<String> funIdList = new ArrayList<>(Arrays.asList(funIds));
            funIdList.remove("-1");
            List<SysFunction> sysFuncs = sysFunctionMapper.findByFunctionIds(funIdList);
            if (sysFuncs != null && sysFuncs.size() > 0) {
                for (SysFunction f : sysFuncs) {
                    funIdList.remove(f.getId());
                }
            }
            if (funIdList.size() > 0) {
                if (logger.isWarnEnabled()) {
                    logger.warn("为角色勾选了无效的系统功能" + funIdList.toString(), new Throwable());
                }
                return new AjaxResult(3000, "为角色勾选了无效的系统功能", null);
            }
        }
        return null;
    }

    @Override
    public AjaxResult<List<Map<String, Object>>> getFuncTypes() {
        List<Map<String, Object>> result = new ArrayList<>();
        Arrays.asList(DataFunctionEnum.values()).forEach(it -> {
            Map<String, Object> map = new HashMap<>();
            map.put("code", it.code);
            map.put("title", it.name);
            result.add(map);
        });
        return new AjaxResult<>(WamingConstant.SUCCESS, "", result);
    }
}
